/*
 * CDCTL01A Basic Example
 * Demonstrates CDCTL01A chip usage with SimpleCDBUS library
 * 
 * Hardware connections:
 * - CDCTL01A CS  -> Arduino Pin 10 (SS)
 * - CDCTL01A INT -> Arduino Pin 2  (INT0)
 * - CDCTL01A MOSI -> Arduino Pin 11 (MOSI)
 * - CDCTL01A MISO -> Arduino Pin 12 (MISO)
 * - CDCTL01A SCK  -> Arduino Pin 13 (SCK)
 * - CDCTL01A VCC  -> 3.3V
 * - CDCTL01A GND  -> GND
 */

#include <SimpleCDCTL.h>

// Pin definitions
const uint8_t CD_CS_PIN = 10;
const uint8_t CD_INT_PIN = 2;

// Create CDCTL01A instance
SimpleCDCTL cdctl(CD_CS_PIN, CD_INT_PIN);

// Device configuration
const uint8_t DEVICE_MAC = 0x01;  // Unique address for this device
const uint32_t BAUD_RATE = 1000000; // 1Mbps

// Communication buffers
uint8_t rx_buffer[64];
uint8_t tx_data[] = "Hello from CDCTL01A!";

// Timing variables
unsigned long last_send = 0;
const unsigned long SEND_INTERVAL = 1000; // Send every 1 second

// Statistics
uint32_t tx_count = 0;
uint32_t rx_count = 0;

void setup() {
    Serial.begin(115200);
    while (!Serial) {
        ; // Wait for serial port
    }
    
    Serial.println("=== CDCTL01A Basic Example ===");
    Serial.print("Device MAC: 0x");
    Serial.println(DEVICE_MAC, HEX);
    Serial.print("Baud Rate: ");
    Serial.println(BAUD_RATE);
    
    // Initialize SPI
    SPI.begin();
    
    // Initialize CDCTL01A
    Serial.println("Initializing CDCTL01A...");
    if (!cdctl.begin(DEVICE_MAC, BAUD_RATE)) {
        Serial.println("Failed to initialize CDCTL01A!");
        while (1) {
            Serial.println("Check connections and reset...");
            delay(2000);
        }
    }
    
    Serial.println("CDCTL01A initialized successfully!");
    
    // Display initial configuration
    Serial.print("MAC Address: 0x");
    Serial.println(cdctl.readRegister(0x02), HEX);
    Serial.print("Status: 0x");
    Serial.println(cdctl.getStatus(), HEX);
    
    // Setup interrupt
    attachInterrupt(digitalPinToInterrupt(CD_INT_PIN), handleInterrupt, FALLING);
    
    Serial.println("Setup complete. Starting communication...");
    Serial.println("Commands:");
    Serial.println("  's' - Send test message");
    Serial.println("  'r' - Read received data");
    Serial.println("  'c' - Show statistics");
    Serial.println("  'i' - Show chip info");
}

void loop() {
    // Check for serial commands
    if (Serial.available()) {
        char cmd = Serial.read();
        handleSerialCommand(cmd);
    }
    
    // Periodic transmission
    if (millis() - last_send >= SEND_INTERVAL) {
        sendPeriodicMessage();
        last_send = millis();
    }
    
    // Check for received data
    if (cdctl.available()) {
        receiveData();
    }
    
    // Handle interrupt-based reception
    if (interrupt_flag) {
        handleInterruptData();
    }
}

// Global interrupt flag
volatile bool interrupt_flag = false;

void handleInterrupt() {
    interrupt_flag = true;
}

void handleInterruptData() {
    noInterrupts();
    interrupt_flag = false;
    interrupts();
    
    // Process any pending data
    while (cdctl.available()) {
        receiveData();
    }
}

void sendPeriodicMessage() {
    if (cdctl.write(tx_data, sizeof(tx_data) - 1)) {
        tx_count++;
        Serial.print("[TX] Sent: ");
        Serial.print((char*)tx_data);
        Serial.print(" (Count: ");
        Serial.print(tx_count);
        Serial.println(")");
    } else {
        Serial.println("[TX] Failed to send message");
    }
}

void receiveData() {
    uint8_t length = cdctl.read(rx_buffer, sizeof(rx_buffer));
    if (length > 0) {
        rx_count++;
        
        Serial.print("[RX] Received ");
        Serial.print(length);
        Serial.print(" bytes: ");
        
        // Print as hex
        for (uint8_t i = 0; i < length; i++) {
            if (rx_buffer[i] < 0x10) Serial.print("0");
            Serial.print(rx_buffer[i], HEX);
            Serial.print(" ");
        }
        
        Serial.print(" | ASCII: ");
        for (uint8_t i = 0; i < length; i++) {
            if (isprint(rx_buffer[i])) {
                Serial.print((char)rx_buffer[i]);
            } else {
                Serial.print(".");
            }
        }
        
        Serial.print(" (Count: ");
        Serial.print(rx_count);
        Serial.println(")");
    }
}

void handleSerialCommand(char cmd) {
    switch (cmd) {
        case 's':
        case 'S':
            Serial.println("Sending test message...");
            sendTestMessage();
            break;
            
        case 'r':
        case 'R':
            Serial.println("Reading any pending data...");
            while (cdctl.available()) {
                receiveData();
            }
            break;
            
        case 'c':
        case 'C':
            showStatistics();
            break;
            
        case 'i':
        case 'I':
            showChipInfo();
            break;
            
        default:
            Serial.println("Unknown command. Use: s=send, r=read, c=stats, i=info");
            break;
    }
}

void sendTestMessage() {
    uint8_t test_msg[] = "Manual test";
    if (cdctl.write(test_msg, sizeof(test_msg) - 1)) {
        Serial.println("Test message sent");
    } else {
        Serial.println("Failed to send test message");
    }
}

void showStatistics() {
    Serial.println("=== Statistics ===");
    Serial.print("TX Count: ");
    Serial.println(tx_count);
    Serial.print("RX Count: ");
    Serial.println(rx_count);
    Serial.print("Status: 0x");
    Serial.println(cdctl.getStatus(), HEX);
    
    // Read some registers for additional info
    Serial.print("MAC: 0x");
    Serial.println(cdctl.readRegister(0x02), HEX);
    Serial.print("Baud L: 0x");
    Serial.println(cdctl.readRegister(0x03), HEX);
    Serial.print("Baud H: 0x");
    Serial.println(cdctl.readRegister(0x04), HEX);
}

void showChipInfo() {
    Serial.println("=== CDCTL01A Info ===");
    Serial.print("Status Register: 0x");
    Serial.println(cdctl.getStatus(), HEX);
    
    Serial.print("Configuration 0: 0x");
    Serial.println(cdctl.readRegister(0x00), HEX);
    
    Serial.print("Configuration 1: 0x");
    Serial.println(cdctl.readRegister(0x01), HEX);
    
    Serial.print("MAC Address: 0x");
    Serial.println(cdctl.readRegister(0x02), HEX);
    
    Serial.print("Baud Rate Low: 0x");
    Serial.println(cdctl.readRegister(0x03), HEX);
    
    Serial.print("Baud Rate High: 0x");
    Serial.println(cdctl.readRegister(0x04), HEX);
    
    Serial.print("Filter Mask 0: 0x");
    Serial.println(cdctl.readRegister(0x05), HEX);
    
    Serial.print("Filter Mask 1: 0x");
    Serial.println(cdctl.readRegister(0x06), HEX);
}